package com.momo.rabbitsingleconsumer.rabbitmq.topic;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.momo.rabbitsingleconsumer.entity.JSONResult;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @program: momo-cloud
 * @description: topic 主题----》消息接收
 * 消息路由规则：四种模式（topic、direct、fanout、header）
 * topic：根据绑定关键字通配符规则匹配、比较灵活
 * direct：默认，根据routingKey完全匹配，好处是先匹配再发送
 * fanout：不需要指定routingkey，相当于群发
 * header：不太常用，可以自定义匹配规则
 * @author: Jie Li
 * @create: 2019-07-27 14:58
 **/
@Component
@Slf4j
public class TopicSingleRabbitReceiver {


    @RabbitListener(bindings = {@QueueBinding(
            value = @Queue(value = TopicSingelRabbitConfig.QUEUE,//队列名称
                    durable = TopicSingelRabbitConfig.DERABLE),//是否持久化
            exchange = @Exchange(value = TopicSingelRabbitConfig.EXCHANGE, //交换机名称
                    durable = TopicSingelRabbitConfig.DERABLE,//是否持久化
                    type = TopicSingelRabbitConfig.TYPE, //消息路由规则
                    ignoreDeclarationExceptions = TopicSingelRabbitConfig.IGNOREDECEXCEPTION), // 忽略声明异常
            key = TopicSingelRabbitConfig.KEY // 绑定的路由键或模式。
    )}
    )
    @RabbitHandler
    public void onMessage(Message message, Channel channel) throws Exception {
        String allMsg = "";
        try {
            allMsg = JSONObject.toJSONString(message);
            log.info("订单消费者收到消息载体：{}", allMsg);
            String msg = new String(message.getBody());
            JSONResult jsonResult= JSON.parseObject(msg, new TypeReference<JSONResult>() {
            });
            log.info("订单消费者收到消息msg：{}", msg);
            String messageId = message.getMessageProperties().getMessageId();
            long deliveryTag = message.getMessageProperties().getDeliveryTag();
            log.info("订单消费者messageId:{},deliveryTag:{}", messageId, deliveryTag);
//            System.out.println(1 / 0);
            //手工ACK
            //第一个deliveryTag参数为每条信息带有的tag值，第二个multiple参数为布尔类型
            //为true时会将小于等于此次tag的所有消息都确认掉，如果为false则只确认当前tag的信息，可根据实际情况进行选择。
            //恢复消息确认成功
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            //拒绝消费消息（丢失消息） 给死信队列
//            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
            //重新分配(消费者会一直消费这条消息，直到消费成功)
//            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
            e.printStackTrace();
            log.error("订单消费者 消费异常:{},{}", allMsg, e.getMessage());
        }

    }
}
